// Copyright DustedPixels.com 2008. All rights reserved.

package com.dustedpixels.dcel;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import com.dustedpixels.dcel.Unit.Component;
import com.dustedpixels.dcel.Unit.Jumper;
import com.dustedpixels.dcel.Unit.Pin;

/**
 * @author micapolos@gmail.com (Michal Pociecha-Los)
 */

public final class UnitWriter {
  final WritingUnitVisitor writingUnitVisitor;
  
  public UnitWriter() {
    this.writingUnitVisitor = new WritingUnitVisitor();
  }
  
  public UnitVisitor getWritingUnitVisitor() {
    return writingUnitVisitor;
  }
  
  public Unit getWrittenUnit() {
    return writingUnitVisitor.getWrittenUnit();
  }
  
  final class WritingUnitVisitor implements UnitVisitor {

    String packageName;
    String unitName;
    List<Pin> pins;
    List<Component> components;
    List<Jumper> jumpers;
    List<String> script;
    
    Unit unit;

    public void visitBegin() {
      unit = null;
      pins = new ArrayList<Pin>();
      components = new ArrayList<Component>();
      jumpers = new ArrayList<Jumper>();
      script = new ArrayList<String>();
    }

    public void visitPackageName(String name) {
      this.packageName = name;
    }

    public void visitUnitName(String name) {
      this.unitName = name;
    }

    public void visitPinsBegin() {

    }

    public void visitPin(final String name) {
      Pin pin = new Pin() {
        public String getName() {
          return name;
        }

        public int getWidth() {
          return 32;
        }
      };
      
      pins.add(pin);
    }

    public void visitPinsEnd() {

    }
    
    public void visitComponentsBegin() {

    }

    public void visitComponent(final String name, final String unitName, final Integer... initArgs) {
      Component component = new Component() {
        public List<Integer> getInitArgs() {
          return Arrays.<Integer>asList(initArgs);
        }

        public String getName() {
          return name;
        }

        public String getUnitName() {
          return unitName;
        }
      };
      
      components.add(component);
    }

    public void visitComponentsEnd() {

    }

    public void visitJumpersBegin() {

    }

    public void visitJumper(
        final String component1Name, 
        final String pin1Name,
        final String component2Name, 
        final String pin2Name) {
      
      Jumper jumper = new Jumper() {
        public String getComponent1Name() {
          return component1Name;
        }

        public String getComponent2Name() {
          return component2Name;
        }

        public String getPin1Name() {
          return pin1Name;
        }

        public String getPin2Name() {
          return pin2Name;
        }
      };
      
      jumpers.add(jumper);
    }

    public void visitJumpersEnd() {

    }

    public void visitScriptBegin() {

    }

    public void visitScriptEntry(String componentName) {
      script.add(componentName);
    }

    public void visitScriptEnd() {

    }

    public void visitEnd() {
      Unit unit = new Unit() {
        public String getName() {
          return unitName;
        }

        public String getPackageName() {
          return packageName;
        }

        public List<Pin> getPins() {
          return Collections.unmodifiableList(pins);
        }

        public List<Component> getComponents() {
          return Collections.unmodifiableList(components);
        }

        public List<Jumper> getJumpers() {
          return Collections.unmodifiableList(jumpers);
        }

        public List<String> getScript() {
          return Collections.unmodifiableList(script);
        } 
      };
      
      this.unit = unit;
    }
    
    Unit getWrittenUnit() {
      if (unit == null) {
        throw new IllegalStateException();
      }
      
      return unit;
    }
  }
}